package com.jsh.erp.service.todoTask;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jsh.erp.constants.BusinessConstants;
import com.jsh.erp.constants.ExceptionConstants;
import com.jsh.erp.datasource.dto.TodoTaskDto;
import com.jsh.erp.datasource.entities.*;
import com.jsh.erp.datasource.mappers.*;
import com.jsh.erp.datasource.vo.TodoTaskVo4List;
import com.jsh.erp.exception.BusinessRunTimeException;
import com.jsh.erp.exception.JshException;
import com.jsh.erp.service.depotHead.DepotHeadService;
import com.jsh.erp.service.log.LogService;
import com.jsh.erp.service.msg.MsgService;
import com.jsh.erp.service.role.RoleService;
import com.jsh.erp.service.user.UserService;
import com.jsh.erp.utils.BaseResponseInfo;
import com.jsh.erp.utils.Constants;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;


/**
 * 信息发送
 * 代办处理
 */
@Service
@Slf4j
public class TodoTaskService {
    private Logger logger = LoggerFactory.getLogger(TodoTaskService.class);
    @Resource
    private TodoTaskMapper todoTaskMapper;
    @Resource
    private DepotHeadService depotHeadService;
    @Resource
    private UserService userService;
    @Resource
    private MsgService msgService;
    @Resource
    private LogService logService;
    @Resource
    private RoleService roleService;

    //--------------------------------------------select----------------------------------------------------------------
    /**
     * 查询条数
     * @param maps
     * @return
     * @throws Exception
     */
    public Long countTodoTask(String taskType,String status,Long creator) throws Exception {
        return todoTaskMapper.findAllListByCount(this.getCurrentUser().getId(),taskType,status,creator);
    }

    /**
     * 查询
     * @param offset
     * @param rows
     * @param taskType
     * @param status
     * @param creator
     * @return
     * @throws Exception
     */
    public List<TodoTaskVo4List> select(int offset, int rows,String taskType,String status,Long creator) throws Exception {
        List<TodoTaskVo4List> allList =
                todoTaskMapper.findAllList(
                        offset,
                        rows,
                        this.getCurrentUser().getId(),
                        taskType,
                        status,
                        creator
                );
        return allList;
    }

    /**
     * 查询当前用户待办信息
     * @param request
     * @return
     */
    public  List<TodoTask> getBacklogById(HttpServletRequest request) {
        List<TodoTask> vals = new ArrayList<>();
        try {

            QueryWrapper<TodoTask> wrapper = new QueryWrapper<>();
            wrapper.eq("assignee_id", roleService.getRoleByUid(userService.getCurrentUser()).getId()).eq("status","未处理");
            vals = todoTaskMapper.selectList(wrapper);
        } catch (Exception e) {
            logger.error("异常码[{}],异常提示[{}],异常[{}]",
                    ExceptionConstants.DATA_READ_FAIL_CODE, ExceptionConstants.DATA_READ_FAIL_MSG,e);
            throw new BusinessRunTimeException(ExceptionConstants.DATA_READ_FAIL_CODE,
                    ExceptionConstants.DATA_READ_FAIL_MSG);
        }
        return vals;
    }
    //--------------------------------------------insert----------------------------------------------------------------
    /**
     * @param head 用户保存的DepotHead数据
     * @return
     * @throws Exception
     */
    @Transactional(value = "transactionManager", rollbackFor = Exception.class)
    public void insertTodoTask(DepotHead head,String statusType,HttpServletRequest request) throws Exception {
        /**
         * 1.校验所选人员下方是否有用户
         * 2.新增待办信息
         * 3.信息提醒
         */

        if(! ObjectUtils.isEmpty(head.getAuditor()) && ! ObjectUtils.isEmpty(head.getTurn())){
            if (roleService.selRoleByUserCount(head.getAuditor()) < 1 || roleService.selRoleByUserCount(head.getTurn()) < 1) {
                throw new BusinessRunTimeException(ExceptionConstants.ROLE_QUERY_FAILED_CODE,
                        String.format(ExceptionConstants.ROLE_QUERY_FAILED_MSG));
            }
        }

        TodoTask task = new TodoTask();
        task.setTaskType(head.getSubType() + ("其它".equals(head.getType()) ? "" : head.getType()) + statusType);
        task.setRelatedId(head.getDefaultNumber());
        task.setAssigneeId(Constants.AUDIT.equals(statusType) ? head.getAuditor() : head.getTurn());
        task.setTurnId(head.getTurn());
        task.setStatus(BusinessConstants.UNPROCESSED);
        task.setCreatorId(head.getCreator());
        task.setBillId(head.getId());
        task.setCreateTime(LocalDateTime.now());
        todoTaskMapper.insert(task);

        Msg msg = new Msg();
        msg.setMsgTitle("你有一个【" + (head.getSubType() + ("其它".equals(head.getType()) ? "" : head.getType()) + statusType) + "】待处理");
        StringBuffer content = new StringBuffer();
        content.append("单据类型：" + (head.getSubType() + ("其它".equals(head.getType()) ? "" : head.getType()) + "<br/>"));
        content.append("任务类型：" + (statusType) + "待办" + "<br/>");
        content.append("单据编号：<a href='/centre/back_log'>" + head.getDefaultNumber() + "</a> <br/>");
        content.append("发起人：" + userService.getCurrentUser().getUsername() + "<br/>");
        content.append("此单据需要您进行处理，请您在左侧侧边栏中依次点击 1.任务审核 -> 2.待办任务 来查看具体单据详情并处理。");
        msg.setMsgContent(content.toString());
        msg.setCreateTime(new Timestamp(System.currentTimeMillis()));
        msg.setType(statusType + "待办");
        msg.setRoleId(Constants.AUDIT.equals(statusType) ? head.getAuditor() : head.getTurn());
        msg.setStatus("1");
        msgService.insertMsg(JSONObject.parseObject(JSONObject.toJSONString(msg)), request);
    }

    /**
     * 根据单据属性设置流程走向。
     */
    @Transactional(rollbackFor = Exception.class)
    public void defaultProcess(DepotHead head,HttpServletRequest request) throws Exception {
        //状态：审核中
        head.setStatus(BusinessConstants.BILLS_STATUS_UNDER_REVIEW);

        //判断flow
        if(BusinessConstants.SUB_TYPE_SALES_ORDER.equals(head.getSubType())){
            //销售单
            //1.抛转人 财务二审
            head.setTurn(roleService.getRoleIdByName("财务"));
            //2.审批人为总经理
            head.setAuditor(roleService.getRoleIdByName("总经理"));
        } else if(BusinessConstants.SUB_TYPE_PURCHASE_ORDER.equals(head.getSubType())){
            //采购单
            //1.审核人
            head.setAuditor(roleService.getRoleIdByName("总经理"));
            //2.抛砖人
            head.setTurn(roleService.getRoleIdByName("采购员"));
        } else if(BusinessConstants.SUB_TYPE_PURCHASE.equals(head.getSubType()) && BusinessConstants.DEPOTHEAD_TYPE_IN.equals(head.getType())){
            //采购入库
            head.setAuditor(roleService.getRoleIdByName("总经理"));
            head.setTurn(roleService.getRoleIdByName("销售员"));
        }  else if(BusinessConstants.SUB_TYPE_SALES.equals(head.getSubType()) && BusinessConstants.DEPOTHEAD_TYPE_OUT.equals(head.getType())){
            head.setAuditor(roleService.getRoleIdByName("总经理"));
            head.setTurn(roleService.getRoleIdByName("仓库经理"));
            //销售出库提醒财务开票！
            /** 发送信息提醒 */
//            Msg msg = new Msg();
//            msg.setMsgTitle("你有一个【开票任务】待处理");
//            StringBuffer content = new StringBuffer();
//            content.append("任务类型：任务待办 <br/>");
//            content.append("单据编号：<a href='/centre/back_log'>" + head.getDefaultNumber() + "</a> <br/>");
//            content.append("发起人：" + userService.getCurrentUser().getUsername() + "<br/>");
//            content.append("此单据需要您进行处理");
//            msg.setMsgContent(content.toString());
//            msg.setCreateTime(new Timestamp(System.currentTimeMillis()));
//            msg.setType("任务待办");
//            msg.setRoleId(roleService.getRoleIdByName("财务"));
//            msg.setStatus("1");
//            msgService.insertMsg(JSONObject.parseObject(JSONObject.toJSONString(msg)), request);
        }
    }

    /**
     * 待办任务审批
     * @param todoTask
     * @param request
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public void taskAuditFlow(TodoTaskDto todoTask,HttpServletRequest request) throws Exception {
        /**
         * 1.得到TodoTask基准数据
         * 2.赋值TodoTask
         * 3.判断流程
         */
        Long taskId = todoTask.getId();
        Assert.notNull(taskId, "任务ID不能为空");
        TodoTask task = todoTaskMapper.selectById(taskId);
        Assert.state(task != null, "未找到待办任务");

        task.setStatusRemark(todoTask.getStatusRemark());
        task.setStatus(todoTask.getAuditResult().compareTo(0L) == BusinessConstants.ZERO?BusinessConstants.REFUSE_N:BusinessConstants.THROUGH);

        Long auditResult = todoTask.getAuditResult();
        if (BusinessConstants.CONSENT_L.compareTo(auditResult) == BusinessConstants.ZERO) {
            sendMessageConsentTpl(task, todoTask.getFileList(), request);
        } else if (BusinessConstants.REFUSE_L.compareTo(auditResult) == BusinessConstants.ZERO) {
            sendMessageRejectTpl(task, request);
        } else {
            throw new BusinessRunTimeException(500, "无效的审核结果状态");
        }
    }

    /**
     * 没有任务的抛转，处理成功信息提醒！
     * @param request
     */
    public void alternativeConsent(TodoTask todo,HttpServletRequest request) throws Exception {
        //1.send message
        Msg msg = new Msg();
        String taskType = todo.getTaskType().substring(0,todo.getTaskType().length()-2);
        msg.setMsgTitle("你提交的"+todo.getTaskType()+"通过了。");
        StringBuffer content = new StringBuffer();
        content.append("单据类型：" + taskType + "<br/>");
        content.append("单据编号：<a href='/centre/back_log' target='_blank'>" + todo.getRelatedId() + "</a> <br/>");
        content.append("审批人：" + getCurrentUser().getUsername() + "<br/>");
        content.append("审批内容："+todo.getStatusRemark()+ "<br/>");
        content.append("请查看后即使处理！");
        msg.setMsgContent(content.toString());
        msg.setCreateTime(new Timestamp(System.currentTimeMillis()));
        msg.setUserId(todo.getCreatorId());
        msgService.insertMsg(JSONObject.parseObject(JSONObject.toJSONString(msg)), request);
    }

    /**
     * 处理审批拒绝流程
     * @param todo 待处理任务
     */
    @Transactional(rollbackFor = Exception.class)
    public void sendMessageRejectTpl(TodoTask todo,HttpServletRequest request) throws Exception {
        /**
         * 1.修改审核状态为未审核
         * 2.发送信息提醒到发起人
         * 3.修改任务记录为拒绝
         */

        HashMap<String, Object> columns = new HashMap<>();
        columns.put("status",BusinessConstants.BILLS_STATUS_UN_AUDIT);
        depotHeadService.updateDepotHeadByMap(columns,todo.getBillId());

        Msg msg = new Msg();
        String taskType = todo.getTaskType().substring(0,todo.getTaskType().length()-2);
        msg.setMsgTitle("你提交的"+todo.getTaskType()+"被拒。");
        StringBuffer content = new StringBuffer();
        content.append("单据类型：" + taskType + "<br/>");
        content.append("单据编号：<a href='/centre/back_log'>" + todo.getRelatedId() + "</a> <br/>");
        content.append("审批人：" + getCurrentUser().getUsername() + "<br/>");
        content.append("审批内容："+todo.getStatusRemark()+ "<br/>");
        content.append("请查看后在对应单据页面进行重新编辑，编辑后将自动进入审批中。");
        msg.setMsgContent(content.toString());
        msg.setCreateTime(new Timestamp(System.currentTimeMillis()));
        msg.setUserId(todo.getCreatorId());
        msgService.insertMsg(JSONObject.parseObject(JSONObject.toJSONString(msg)), request);

        todoTaskMapper.updateById(todo);
    }

    /**
     * 处理审批同意流程
     * @param todo 待处理任务
     */
    @Transactional(rollbackFor = Exception.class)
    public void sendMessageConsentTpl(TodoTask todo,String fileList,HttpServletRequest request) throws Exception {
        /**
         * 同意审核
         * 1.判断下方有二审（如有 新增）
         * 2.增加附件信息
         */
        DepotHead head = depotHeadService.getDepotHead(todo.getBillId());
        Assert.notNull(head,"任务执行错误----billId");

        if(BusinessConstants.SUB_TYPE_SALES_ORDER.equals(head.getSubType())){
            //销售订单需要二审！
            if(roleService.getRoleIdByName("总经理").compareTo(head.getAuditor()) == BusinessConstants.ZERO){
                head.setAuditor(roleService.getRoleIdByName("财务"));
                head.setTurn(roleService.getRoleIdByName("采购员"));
                depotHeadService.updateDepotHead(head);
                insertTodoTask(head,Constants.AUDIT,request);
            }else{
                //改变单据审核状态为已审核！发送任务到采购
                depotHeadService.batchSetStatus(BusinessConstants.CONSENT,todo.getBillId()+"");
                insertTodoTask(head,Constants.TURN,request);
            }
        }else{
            //改变单据审核状态为已审核！
            depotHeadService.batchSetStatus(BusinessConstants.CONSENT,todo.getBillId()+"");

            //如果是采购订单 只需要提醒即可！
            if(BusinessConstants.SUB_TYPE_PURCHASE_ORDER.equals(head.getSubType())){
                alternativeConsent(todo,request);
            }else{
                insertTodoTask(head,Constants.TURN,request);
            }
        }

        //更新当前todo状态
        todoTaskMapper.updateById(todo);

        //附件
        head.setFileName(ObjectUtils.isEmpty(head.getFileName())?fileList:head.getFileName()+","+fileList);
        if (!ObjectUtils.isEmpty(fileList)) {
            HashMap<String, Object> val = new HashMap<>();
            val.put("file_name",head.getFileName());
            depotHeadService.updateDepotHeadByMap(val,todo.getBillId());
        }
    }


    //--------------------------------------------update----------------------------------------------------------------
    /**
     * 功能：待办任务完成
     * @param id
     */
    public void taskFinished(Long id) {
        //todo:少一个校验真正是否完成的功能！
        TodoTask task = todoTaskMapper.selectById(id);
        Assert.notNull(task,"当前任务id错误！");

        task.setStatus("已处理");
        task.setProcessingTime(LocalDateTime.now());
        int update = todoTaskMapper.updateById(task);

        if(update<=BusinessConstants.ZERO.intValue()){
            throw new BusinessRunTimeException(ExceptionConstants.USER_EDIT_FAILED_CODE,ExceptionConstants.USER_EDIT_FAILED_MSG);
        }
    }
    //--------------------------------------------delete----------------------------------------------------------------
    //--------------------------------------------other-----------------------------------------------------------------
    /**
     * 获取User对象
     * @return
     * @throws Exception
     */
    private User getCurrentUser() throws Exception {
        return userService.getCurrentUser();
    }

    /**
     * 发送信息
     */
    public void sendMsg(Long userId,DepotHead head,HttpServletRequest request) throws Exception {
        User user = userService.getUser(userId);
        Msg msg = new Msg();
        msg.setMsgTitle("ERP系统抄送通知");
        StringBuffer content = new StringBuffer();
        content.append("主题: ["+head.getSubType()+"] - [简要描述] 通知 <br/>");
        content.append("尊敬的["+user.getUsername()+"]，<br/>");
        content.append("您好！<br/>");
        content.append("为了确保["+head.getSubType()+"]的顺利进行，以下是来自ERP系统的最新信息，请您知悉并根据需要采取相应行动。<br/>");
        content.append("<h2>通知详情</h2>");
        content.append("事件类型: "+head.getSubType()+"创建");
        content.append("订单编号: ["+head.getDefaultNumber()+"]");
        content.append("发生时间: ["+head.getCreateTime()+"]");
        msg.setMsgContent(content.toString());
        msg.setCreateTime(new Timestamp(System.currentTimeMillis()));
        msg.setType("提醒");
        msg.setUserId(userId);
        msg.setStatus("1");
        msgService.insertMsg(JSONObject.parseObject(JSONObject.toJSONString(msg)), request);
    }
}
